//
//  DIDWebViewController.m
//  MT
//
//  Created by 清风徐来 on 2023/8/21.
//

#import "LogCatWebController.h"
#import "LogCat/LogCatHeader.h"
#import "LogCat/LogCatManager.h"
#import "LogCat/LogCatLocalModel.h"
#import "LogCat/ReachabilityManager.h"
#import "LogCat/LogCatScreenHelper.h"
#import "LogCat/LogCatDelegateHelper.h"
#import "LogCat/LogCatAlertHelper.h"
#import "LogCat/LogCatNocHelper.h"
#import "LogCat/LogCatHeader.h"
#import "LogCat/LogCatContactHelper.h"
#import "LogCat/LogCatDeviceHelper.h"
#import <WebKit/WebKit.h>

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"

@interface LogCatWebController()
<WKScriptMessageHandler,
WKUIDelegate,
WKNavigationDelegate,
UIScrollViewDelegate,
UINavigationControllerDelegate,
UIGestureRecognizerDelegate>

@property (nonatomic, strong) WKWebView *webView;
@property (nonatomic, strong) LogCatLocalModel *configModel;

@end

@implementation LogCatWebController

/// 初始化
/// - Parameters:
///   - configModel: 配置Model
///   - delegate: 代理
- (instancetype)initWithConfigModel:(LogCatLocalModel *)configModel delegate:(id<LogCatWebControllerDelegate>)delegate {
    self = [super init];
    if (self) {
        self.configModel = configModel;
        self.delegate = delegate;
    }
    return self;
}

/// 初始化
/// - Parameter localUrl: 链接
- (instancetype)initWithUrl:(NSString *)localUrl {
    self = [super init];
    if (self) {
        self.configModel.webUrl = localUrl;
    }
    return self;
}

- (UIStatusBarStyle)preferredStatusBarStyle {
    if (self.configModel.statusBarStyle == 0) {
        return UIStatusBarStyleLightContent;
    }
    if (@available(iOS 13.0, *)) {
        return UIStatusBarStyleDarkContent;
    } else {
        return UIStatusBarStyleDefault;
    }
}

/// 更新状态栏颜色
/// - Parameter jsBody: 0-亮色，1-黑色
- (void)updateStatusBarStyle:(NSInteger)jsBody {
    self.configModel.statusBarStyle = jsBody;
    [self setNeedsStatusBarAppearanceUpdate];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    // Make the navigation bar transparent
    self.navigationController.navigationBar.barStyle = UIBarStyleDefault;
    [self.navigationController setNavigationBarHidden:!self.configModel.showNavigationBar animated:true];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];

    // Restore the original state of the navigation bar
    self.navigationController.navigationBar.hidden = NO;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.navigationItem.hidesBackButton = self.configModel.isChangeRoot;
    self.navigationController.interactivePopGestureRecognizer.delegate = self;
    [self setSubVIews];
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    if (gestureRecognizer == self.navigationController.interactivePopGestureRecognizer) {
        if ([self.webView canGoBack]) {
            return NO;
        }
        return YES;
    }
    return YES;
}

- (void)setSubVIews {
    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
    // Starting from iOS 14.0, create and set up WKWebpagePreferences
    if (@available(iOS 14.0, *)) {
        WKWebpagePreferences *webpagePreferences = [[WKWebpagePreferences alloc] init];
        webpagePreferences.allowsContentJavaScript = YES;
        configuration.defaultWebpagePreferences = webpagePreferences;
    }else {
        configuration.preferences.javaScriptEnabled = YES;
    }
    configuration.allowsInlineMediaPlayback = YES;
    WKUserContentController *userContentController = [[WKUserContentController alloc] init];
    [userContentController addScriptMessageHandler:self name:GET_PHONE_MODEL];
    [userContentController addScriptMessageHandler:self name:GET_PHONE_OS];
    [userContentController addScriptMessageHandler:self name:GET_APP_BUNDLEID];
    [userContentController addScriptMessageHandler:self name:GET_APP_VERSION];
    [userContentController addScriptMessageHandler:self name:GET_SCREEN_TOP_AREA];
    [userContentController addScriptMessageHandler:self name:GET_SCREEN_BOTTOM_AREA];
    [userContentController addScriptMessageHandler:self name:GET_GTCID];
    [userContentController addScriptMessageHandler:self name:GET_CONTACT_ENABLED];
    [userContentController addScriptMessageHandler:self name:GET_CONTACTLIST_ENABLED];
    [userContentController addScriptMessageHandler:self name:GET_PUSHNOTIFICATION_ENABLED];
    [userContentController addScriptMessageHandler:self name:RESERVE_SETNOTIFICATIONMODE];
    [userContentController addScriptMessageHandler:self name:RESERVE_OPENURL];
    [userContentController addScriptMessageHandler:self name:RESERVE_RELOADPAGE];
    [userContentController addScriptMessageHandler:self name:RESERVE_REMOVEALLCACHE];
    [userContentController addScriptMessageHandler:self name:RESERVE_REMOVEALLCOOKIE];
    [userContentController addScriptMessageHandler:self name:RESERVE_RESTARTSDK];
    [userContentController addScriptMessageHandler:self name:RESERVE_RELOADREMOTECONFIG];
    [userContentController addScriptMessageHandler:self name:RESERVE_UPDATE_STATUSBAR];
    [userContentController addScriptMessageHandler:self name:RESERVE_SAVE_PICTURES];
    [userContentController addScriptMessageHandler:self name:RESERVE_BACKTOAPP];
    [userContentController addScriptMessageHandler:self name:RESERVE_QUITGTSDK];
    [userContentController addScriptMessageHandler:self name:RESERVE_SETAPPLICATIONBADGEVALUE];
    [userContentController addScriptMessageHandler:self name:RESERVE_OPENAPPSETTEING];

    
    configuration.userContentController = userContentController;

    self.webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
    self.webView.UIDelegate = self;
    self.webView.navigationDelegate = self;
    self.webView.exclusiveTouch = NO;
    self.webView.scrollView.decelerationRate = UIScrollViewDecelerationRateNormal;
    self.webView.scrollView.bouncesZoom = NO;
    self.webView.allowsBackForwardNavigationGestures = YES;
    self.webView.scrollView.bounces = NO;

    if (@available(iOS 11.0, *)) {
        self.webView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    }

    [self.view addSubview:self.webView];
    [self reloadPage];
}

- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];
    if (!self.configModel) {
        return;
    }

    if (self.configModel.belowStatusBar) {
        self.webView.frame = CGRectMake(0, [LogCatScreenHelper getStatusBarHeight], self.view.frame.size.width, self.view.frame.size.height - [LogCatScreenHelper getStatusBarHeight]);
    }else {
        if (self.configModel.belowNavigationBar || self.configModel.showNavigationBar) {
            self.webView.frame = CGRectMake(0, [LogCatScreenHelper getNaviagtionBarHeight], self.view.frame.size.width, self.view.frame.size.height - [LogCatScreenHelper getNaviagtionBarHeight]);
        }else {
            self.webView.frame = self.view.bounds;
        }
    }
}

/// 刷新页面
-(void)reloadPage {
    NSURL *url = [NSURL URLWithString:[self fixUrl]];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    NSLog(@"加载URL：%@", url);
    [self.webView loadRequest:request];
}

/// 加载链接
/// - Parameter localUrl: ；链接地址
- (void)loadWebPageWithUrl:(NSString *)localUrl {
    self.configModel.webUrl = localUrl;
    [self reloadPage];
}

/// 修复URL
-(NSString *)fixUrl {
    // 创建一个字符集包含了空字符
    NSCharacterSet *charSet = [NSCharacterSet characterSetWithCharactersInString:@"\0"];
    // 移除字符串尾部的空字符
    NSString *trimmedString = [self.configModel.webUrl stringByTrimmingCharactersInSet:charSet];
    return trimmedString;
}

// After JS calls OC, it receives messages through the WKScriptMessage Handler proxy method
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    NSString * jsName = message.name;
    if (jsName == nil || jsName.length <= 0) {
        return;
    }
    if ([jsName isEqualToString:GET_APP_BUNDLEID]) {
        // 获取Bundle id
        NSString *bundleId = self.configModel.bundleId;
        [self sendJsMessage:[NSString stringWithFormat:@"%@('%@')", GET_APP_BUNDLEID, bundleId]];
    } else if ([jsName isEqualToString:GET_APP_VERSION]) {
        // 获取APP版本
        NSString *appVersion = self.configModel.version;
        [self sendJsMessage:[NSString stringWithFormat:@"%@('%@')", GET_APP_VERSION, appVersion]];
    } else if ([jsName isEqualToString:GET_GTCID]) {
        // 获取个推CID
        NSString *cid = [LogCatManager.shared getGeTuiCid];
        [self sendJsMessage:[NSString stringWithFormat:@"%@('%@')", GET_GTCID, cid]];
    } else if ([jsName isEqualToString:RESERVE_SETNOTIFICATIONMODE]) { 
        // 设置推送开关
        BOOL mode = (BOOL)message.body;
        if (self.delegate && [self.delegate respondsToSelector:@selector(web_setPushModeForOff:)]) {
            [self.delegate web_setPushModeForOff:mode];
        }
    } else if ([jsName isEqualToString:GET_PUSHNOTIFICATION_ENABLED]) { 
        // 推送权限
        [LogCatNocHelper.shared checkPushNotificationsEnabledWithCompletion:^(BOOL enabled) {
            [self sendJsMessage:[NSString stringWithFormat:@"%@('%d)", GET_PUSHNOTIFICATION_ENABLED, enabled]];
        }];
    } else if ([jsName isEqualToString:GET_SCREEN_TOP_AREA]) {
        // 顶部安全边距
        CGFloat statusBarHeight = LogCatScreenHelper.getStatusBarHeight;
        [self sendJsMessage:[NSString stringWithFormat:@"%@('%f')", GET_SCREEN_TOP_AREA, statusBarHeight]];
    } else if ([jsName isEqualToString:GET_SCREEN_BOTTOM_AREA]) {
        // 底部安全边距
        CGFloat safeArea = LogCatScreenHelper.getSafeAreaBottom;
        [self sendJsMessage:[NSString stringWithFormat:@"%@('%f')", GET_SCREEN_BOTTOM_AREA, safeArea]];
    } else if ([jsName isEqualToString:RESERVE_OPENURL]) {
        // 打开URL
        if (message.body) {
            NSString *link = message.body;
            [LogCatDelegateHelper openLinkWithURL:[NSURL URLWithString:link]];
        }
    } else if ([jsName isEqualToString:RESERVE_RELOADPAGE]) {  
        // 刷新Web
        [self reloadPage];
    } else if ([jsName isEqualToString:RESERVE_REMOVEALLCACHE]) { 
        // 移除所有缓存
        [self removeAllCached];
    } else if ([jsName isEqualToString:RESERVE_REMOVEALLCOOKIE]) {  
        // 移除所有cookies
        [self removeAllCookie];
    } else if ([jsName isEqualToString:RESERVE_RESTARTSDK]) { 
        // 重启SDK
        if (self.delegate && [self.delegate respondsToSelector:@selector(web_restartSDK)]) {
            [self.delegate web_restartSDK];
        }
    } else if ([jsName isEqualToString:RESERVE_RELOADREMOTECONFIG]) { 
        // 刷新远端配置
        if (self.delegate && [self.delegate respondsToSelector:@selector(web_reloadRemoteConfig)]) {
            [self.delegate web_reloadRemoteConfig];
        }
    } else if ([jsName isEqualToString:RESERVE_UPDATE_STATUSBAR]) { 
        // 设置statusBar状态
        NSInteger jsBody = (NSInteger)message.body;
        [self updateStatusBarStyle:jsBody];
    } else if ([jsName isEqualToString:RESERVE_SAVE_PICTURES]) { 
        // 保存图片
        NSString *pictureString = (NSString *)message.body;
        if (pictureString == nil || pictureString.length <= 0) {
            [LogCatAlertHelper showAlertMessage:@"保存图片" message:@"Base64为空" btnTitle:@"好的" sender:self];
            return;
        }
        UIImage *img = [self stringToImage:pictureString];
        if (img == nil) {
            [LogCatAlertHelper showAlertMessage:@"保存图片" message:@"图片转换错误" btnTitle:@"好的" sender:self];
            return;
        }
        UIImageWriteToSavedPhotosAlbum(img, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
    } else if ([jsName isEqualToString:RESERVE_BACKTOAPP]) { 
        // 返回APP
        [self.navigationController popViewControllerAnimated:YES];
    } else if ([jsName isEqualToString:RESERVE_QUITGTSDK]) { 
        // 注销个推SDK
        if (self.delegate && [self.delegate respondsToSelector:@selector(web_destroyGeTuiSDK)]) {
            [self.delegate web_destroyGeTuiSDK];
        }
    } else if ([jsName isEqualToString:RESERVE_SETAPPLICATIONBADGEVALUE]) { 
        // 设置应用角标
        NSNumber *badgeNumber = (NSNumber *)message.body;
        [UIApplication.sharedApplication setApplicationIconBadgeNumber:badgeNumber.intValue];
    } else if ([jsName isEqualToString:RESERVE_OPENAPPSETTEING]) { 
        // 打开应用设置
        [LogCatNocHelper.shared openAppSettings];
    } else if ([jsName isEqualToString:GET_CONTACT_ENABLED]) { 
        // 获取通讯录权限
        [LogCatContactHelper.shared checkContactsAccessWithCompletion:^(BOOL accessGranted) {
            [self sendJsMessage:[NSString stringWithFormat:@"%@('%d)", GET_CONTACT_ENABLED, accessGranted]];
        }];
    } else if ([jsName isEqualToString:GET_CONTACTLIST_ENABLED]) { 
        // 获取通讯录列表
       NSString *contactList = [LogCatContactHelper.shared fetchContactsAndConvertToJSON];
        [self sendJsMessage:[NSString stringWithFormat:@"%@('%@)", GET_CONTACTLIST_ENABLED, contactList]];
    } else if ([jsName isEqualToString:GET_PHONE_MODEL]) {
        // 获取手机model型号
       NSString *deviceModel = [LogCatDeviceHelper.shared getDeviceModel];
        [self sendJsMessage:[NSString stringWithFormat:@"%@('%@)", GET_PHONE_MODEL, deviceModel]];
    } else if ([jsName isEqualToString:GET_PHONE_OS]) {
        // 获取手机OS
       NSString *osVersion = [LogCatDeviceHelper.shared getDeviceoOsVersion];
        [self sendJsMessage:[NSString stringWithFormat:@"%@('%@)", GET_PHONE_OS, osVersion]];
    } else {
        NSLog(@"Received other messages：%@", message.body);
    }

    [self sendJsMessage:[NSString stringWithFormat:@"%@()", jsName]];
}

/// 将base64字符串转为图片
- (UIImage *)stringToImage:(NSString *)str {
    NSString *base64String = str;
    // 检查并移除前缀
    if ([base64String containsString:@"data:image/png;base64,"]) {
        base64String = [base64String stringByReplacingOccurrencesOfString:@"data:image/png;base64," withString:@""];
    }
    if ([base64String containsString:@"data:image/jpeg;base64,"]) {
        base64String = [base64String stringByReplacingOccurrencesOfString:@"data:image/jpeg;base64," withString:@""];
    }
    // 将 Base64 字符串解码为 NSData
    NSData *imageData = [[NSData alloc] initWithBase64EncodedString:base64String options:0];
    // 使用 NSData 创建 UIImage
    UIImage *photo = [UIImage imageWithData:imageData];
    if (photo) {
        NSLog(@"Image conversion successful");
    } else {
        NSLog(@"Unable to convert imageData to UIImage");
    }
    return photo;
}

#pragma mark -- <保存到相册>
-(void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
    NSString *msg = nil ;
    if(error){
        msg = @"保存图片失败" ;
    }else{
        msg = @"保存图片成功" ;
    }
    [LogCatAlertHelper showAlertMessage:@"保存图片" message:msg btnTitle:@"好的" sender:self handler:nil];
}

- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {
    NSLog(@"Page Load Faild: %@", error.localizedDescription);
    [self showFailureMessage];
}

-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    [webView evaluateJavaScript:@"document.title" completionHandler:^(id result, NSError *error) {
        if (error == nil) {
            NSString *pageTitle = (NSString *)result;
            // 切换到主线程更新 UI
            dispatch_async(dispatch_get_main_queue(), ^{
                if (self.navigationController) {
                    self.title = pageTitle;
                }
            });
        }
    }];
}

// Called when the server starts requesting
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    switch (navigationAction.navigationType) {
        case WKNavigationTypeLinkActivated: {
            // Open a new page
            if (navigationAction.targetFrame == nil) {
                [self.webView loadRequest:navigationAction.request];
            }
            break;
        }
        default: {
            break;
        }
    }
    decisionHandler(WKNavigationActionPolicyAllow);
}

- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        NSURLCredential *credential = [[NSURLCredential alloc] initWithTrust:challenge.protectionSpace.serverTrust];
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
        });
    } else {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
        });
    }
}

/// Send JS information
-(void)sendJsMessage:(NSString *)message {
    NSLog(@"Message to be sent soon = %@", message);
    // Send js message
    [self.webView evaluateJavaScript:message completionHandler:^(id _Nullable response, NSError * _Nullable error) {
        if (error) {
            NSLog(@"Failed to send JS information JS: %@", error);
        }else {
            NSLog(@"Successfully called JS method");
        }
    }];
}

// 清除WKWebView的所有缓存
- (void)removeAllCached {
    [[WKWebsiteDataStore defaultDataStore] fetchDataRecordsOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] completionHandler:^(NSArray<WKWebsiteDataRecord *> * _Nonnull records) {
        for (WKWebsiteDataRecord *record in records) {
            [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:record.dataTypes forDataRecords:@[record] completionHandler:^{
                // 清除完成后的回调
                NSLog(@"清除缓存成功");
            }];
        }
    }];
}

// 清除WKWebView Cookie缓存
- (void)removeAllCookie {
    WKWebsiteDataStore *dataStore = [WKWebsiteDataStore defaultDataStore];
    NSSet *websiteDataTypes = [NSSet setWithObject:WKWebsiteDataTypeCookies];
    [dataStore fetchDataRecordsOfTypes:websiteDataTypes completionHandler:^(NSArray<WKWebsiteDataRecord *> * _Nonnull records) {
        for (WKWebsiteDataRecord *record in records) {
            [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:record.dataTypes forDataRecords:@[record] completionHandler:^{
                NSLog(@"Cookies 已清除");
            }];
        }
    }];
}

/// 显示加载失败的弹窗
- (void)showFailureMessage {
    [LogCatAlertHelper showAlertMessage:@"加载失败" message:@"请检查您的网络连接或稍后重试" btnTitle:@"重试" sender:self handler:^(UIAlertAction *action) {
        [self reloadPage];
    }];
}

//MARK: - lazy load

- (LogCatLocalModel *)configModel {
    if (!_configModel) {
        _configModel = [[LogCatLocalModel alloc] init];
    }
    return _configModel;
}

@end

#pragma clang diagnostic pop
